home *** CD-ROM | disk | FTP | other *** search
/ Internet Surfer 2.0 / Internet Surfer 2.0 (Wayzata Technology) (1996).iso / pc / text / mac / faqs.383 < prev    next >
Text File  |  1996-02-12  |  28KB  |  760 lines

  1. Frequently Asked Questions (FAQS);faqs.383
  2.  
  3.  
  4.  
  5. Answer: If you press the help key the help callback of the widget with the
  6. keyboard focus is called (not the one containing the mouse).  You can't get
  7. the help callback of a non-keyboard-selectable widget called. To get `context
  8. sensitive' help on these, you have to find the mouse, associate its position
  9. with a widget and then do the help.
  10.  
  11.  
  12.  
  13. -----------------------------------------------------------------------------
  14. Subject: 130) Where can I get a Table widget?
  15.  
  16. Answer: Send email to Kee Hinckley (nazgul@alfalfa.com) asking for a copy of
  17. his table widget.  The Widget Creation Library also has one.  See under Motif
  18. prototyping tools for the contact.
  19.  
  20. Expert Database Systems, Inc., 305 Madison Ave, Suite 1166, New York, NY 10165
  21. has a very comprehensive table widget that uses both motif scrollbars or a
  22. "virtual" scrollbar showing a miniature version of the entire spreadsheet.
  23. Allows for different width columns, changing colors in each cell.  Only one
  24. X-Window is used so as to reduce the amount of system resources used.  Contact
  25. Ken Jones
  26.  
  27.  
  28. -----------------------------------------------------------------------------
  29. Subject: 131)  Has anyone done a bar graph widget?
  30. [Last modified: September 92]
  31.  
  32. Answer: You can fake one by using for each bar a scroll bar or even a label
  33. which changes in size, put inside a container of some kind.
  34.  
  35. Try the StripChart widget in the Athena widget set. Set the XtNupdate resource
  36. to 0 to keep it from automatically updating.
  37.  
  38. The comp.windows.x FAQ mentions a bar graph widget.
  39.  
  40. Expert Database Systems, Inc.  sells a bar graph widget as well as a multi-
  41. line graph with automatic scaling, a 3-D surface graph, and a high/Low graph
  42. with two lines for moving averages.  Contact Ken Jones Expert Database
  43. Systems, Inc., 305 Madison Ave, Suite 1166, New York, NY 10165, Main Number:
  44. (212) 370-6700, Phone Mail:  (212) 714-8345
  45.  
  46. The Xtra XWidget library contains a set of widgets that are subclassed from
  47. and compatible with either OSF/Motif or OLIT widgets.  The library includes
  48. widgets that implement the following:
  49.  
  50.    Spreadsheet
  51.    Bar Graph
  52.    Stacked Bar Graph
  53.    Line Graph
  54.    Pie Chart
  55.    XY Plot
  56.    Hypertext
  57.    Hypertext based Help System
  58.    Entry Form with type checking
  59.  
  60. Contact Graphical Software Technology at 310-328-9338  (info@gst.com) for
  61. information.
  62.  
  63. The XRT/graph widget, available for Motif, XView and OLIT, displays X-Y plots,
  64. bar and pie charts, and supports user-feedback, fast updates and PostScript
  65. output. Contact KL Group Inc. at 416-594-1026 (xrt_info%klg@uunet.ca)
  66.  
  67. The product Xmath, made by Integrated Systems Inc. is a product which has
  68. interactive 2d and 3d graphics for bar,strip,line,symbol,
  69. surface,contour,etc... that costs $2500.00 for commercial use and a mere
  70. $250.00 for university use that also has complete numerics capabilities, an
  71. easy to use debugger, a complete high level language, a spreadsheet, a motif
  72. gui access capability, and much more all created on top of motif.
  73.  
  74. You can either email to xmath-info@isi.com or call (408)980-1500.
  75.  
  76. Digital Equipment Corporation (DEC) provides the following product NetEd: "The
  77. network editor widget is a Motif toolkit conforming widget that applications
  78. can use to express complex interrelationships graphically in the form of
  79. networks or graphs. The network editor supports interactive or application-
  80. controlled creation and editing of directed graphs or networks."
  81.  
  82.  
  83. ACE/gr is an X based XY plotting tool implemented with a point 'n click
  84. paradigm.  A few of its features are:
  85.  
  86.    * Plots up to 10 graphs with 30 data sets per graph.
  87.    * Data read from files and/or pipes.
  88.    * Graph types XY, log-linear, linear-log, log-log, bar,
  89.         stacked bar charts.
  90.  
  91. it is available from
  92.  
  93.         ftp.ccalmr.ogi.edu (presently amb4.ccalmr.ogi.edu)
  94.  
  95. with IP address 129.95.72.34. The XView version (xvgr) will be found in
  96. /CCALMR/pub/acegr/xvgr-2.09.tar.Z and the Motif version (xmgr) in
  97. /CCALMR/pub/acegr/xmgr-2.09.tar.Z.  Comments, suggestions, bug reports to
  98. pturner@amb4.ccalmr.ogi.edu (if mail fails, try pturner@ese.ogi.edu). Due to
  99. time constraints, replies will be few and far between.
  100.  
  101.  
  102.  
  103. -----------------------------------------------------------------------------
  104. Subject: 132)  Does anyone know of a source code of a graph widget where you
  105. can add vertices and edges and get an automated updating?
  106.  
  107. [Last modified: September 92]
  108.  
  109. Answer: The XUG FAQ in comp.windows.x includes information on graph display
  110. widgets.  There is also an implementation in the Asente/Swick book.
  111.  
  112.   From Martin Janzen: "You could have a look at DataViews, from V.I.
  113.    Corporation.  This package is used mainly to display a variety of graph
  114.    drawings (eg. bar, line, pie, high/low, and other charts), and to update
  115.    the graphs as information is received from "data sources" such as files,
  116.    processes (through pipes), or devices.
  117.  
  118.    However, it also provides "node" and "edge" objects which can be used
  119.    when working with network graphs.  The DV-Tools function library
  120.    provides routines which traverse a graph, count visits to each node or
  121.    edge, mark nodes or edges of interest, and so on.  A node or edge object
  122.    can have an associated "geometry object" (such as a symbol or a line),
  123.    which represents that node or edge.
  124.  
  125.    Drawbacks: There's no automatic positioning algorithm; when you add a
  126.    node or edge, you have to create and position its geometry object
  127.    yourself.  Also, this isn't a set of add-on widgets; you can either have
  128.    DataViews create an X window (ie. a separate shell), or you can create
  129.    your own XmDrawingArea and use DataViews to update its window when
  130.    expose events are received.  Finally, the package is quite expensive,
  131.    and there is a run-time charge.
  132.  
  133.    The vendor's address is:
  134.      V.I. Corporation,
  135.      47 Pleasant Street,
  136.      Northampton, MA  01060,
  137.             Email: vi@vicorp.com, Phone: (413) 586-4144, Fax:   (413) 584-2649
  138.  
  139.    or
  140.  
  141.      V.I. Corporation (Europe) Ltd.,
  142.      First Base, Beacontree Plaza,
  143.      Gillette Way,                      Email: viesales@eurovi.uucp
  144.      Reading, Berkshire  RG2 0BP"
  145.    Phone: +44 734 756010,      Fax:   +44 734 756104
  146.  
  147. From Craig Timmerman: Just wanted others to know that there is a third
  148. competitor in what may be come a big market for generic APIs.  The product is
  149. called Open Interface and Neuron Data is the vendor.  Neuron has added some
  150. extra, more complex widgets to their set.  The two most notable are a table
  151. and network widget.  [...] I believe that the network widget got its name from
  152. its ability to display expert system networks that Neuron's AI tools needed.
  153. It would be more aptly named the graph widget.  It can display and manipulate
  154. graphs of various types (trees, directed graphs, etc).  Contact is
  155.  
  156.         Neuron Data
  157.         156 University Avenue
  158.         Palo Alto,  CA  94301
  159.         (415) 321-4488
  160.  
  161.  
  162. prism!gt3273b@gatech.edu  (RENALDS,ANDREW THEODORE) posted a set of public
  163. domain routines for graph drawing.  Contact him for a later set.
  164.  
  165. From Ramon Santiago (santiago@fgssu1.fgs.slb.com): HP has released source code
  166. for XmGraph and XmArc, part of the InterWorks library, which does exactly
  167. this. The sources can be obtained by contacting Dave Shaw,
  168. librarian@iworks.ecn.uiowa.edu. A few trivial source code changes need to be
  169. made to get these widgets to compile under Motif 1.2.
  170.  
  171.  
  172. -----------------------------------------------------------------------------
  173. Subject: 133)  Is there a help system available, such as in Windows 3?  Or any
  174. Motif based hypertext system.
  175.  
  176. Answer:
  177.  
  178. Bristol Technology have a hypertext system HyperHelp with the look-and-feel of
  179. either Motif or OpenLook. It should be available from january 31, 1992.
  180. Contact
  181.  
  182.         Bristol Technology Inc.
  183.         898 Ethan Allen Highway
  184.         Ridgefield, CT  06877
  185.         203-438-6969 (phone)
  186.         203-438-5013 (fax)
  187.         uunet.uu.net!bristol!keith
  188.  
  189. Demos are available by anonymous ftp from  ftp.uu.net (137.39.1.9) in the
  190. vendor/Bristol/HyperHelp as files sun.motif.tar.Z and hp.tar.Z.
  191.  
  192. There was a posting of a motif hypertext-widget to comp.sources.x (Author:
  193. B.Raoult ( mab@ecmwf.co.uk ) ).  It had the facility to read in helptext from
  194. a file.
  195.  
  196. From Francois Felix Ingrand (felix@idefix.laas.fr): I have translated the Info
  197. AW (originally written by Jordan Hubbard) to Motif. It is a Widget to browse
  198. Info files (format used by GNU for their various documentations). I use it as
  199. the help system of various tool I wrote.  It is available on laas.laas.fr
  200. (140.93.0.15) in /pub/prs/xinfo-motif.tar.Z
  201.  
  202. Form Scott Raney (raney@metacard.com) MetaCard is a commercial package that
  203. can be used to implement hypertext help.  The text fields support multiple
  204. typefaces, sizes, styles, colors, subscript/superscript, and hypertext links.
  205. It has a Motif interface, and a template for calling it from an Xt/Motif
  206. application is included.  You can FTP a save-disabled distribution from
  207. ftp.metacard.com or from world.std.com.  For more info, email to
  208. info@metacard.com.
  209.  
  210.  
  211.  
  212.  
  213. -----------------------------------------------------------------------------
  214. Subject: 134) Can I specify a widget in a resource file?
  215.  
  216. Answer: This answer, which uses the Xmu library, is due to David Elliott.  If
  217. the converter is added, then the name of a widget (a string) can be used in
  218. resource files, and will be converted to the appropriate widget.
  219.  
  220. This code, which was basically stolen from the Athena Form widget, adds a
  221. String to Widget converter.  I wrote it as a general routine that I call at
  222. the beginning of all of my programs, and made it so I could add other
  223. converters as needed (like String to Unit Type ;-).
  224.  
  225.         #include <X11/Intrinsic.h>
  226.         #include <X11/StringDefs.h>
  227.         #include <Xm/Xm.h>
  228.         #include <X11/Xmu/Converters.h>
  229.         #include <X11/IntrinsicP.h>
  230.         #include <X11/CoreP.h>
  231.  
  232.         void
  233.         setupConverters()
  234.         {
  235.                 static XtConvertArgRec parentCvtArgs[] = {
  236.                         {XtBaseOffset, (caddr_t)XtOffset(Widget, core.parent),
  237.                                 sizeof(Widget)}
  238.                 };
  239.  
  240.                 XtAddConverter(XmRString, XmRWindow, XmuCvtStringToWidget,
  241.                         parentCvtArgs, XtNumber(parentCvtArgs));
  242.         }
  243.  
  244.  
  245.  
  246. -----------------------------------------------------------------------------
  247. Subject: 135) Why are only some of my translations are being installed?  I
  248. have a translation table like the following, but only the first ones are
  249. getting installed and the rest are ignored.
  250.  
  251.  *Text.translations:    #override \
  252.      Ctrl<Key>a:    beginning-of-line() \n\
  253.      Ctrl<Key>e:    end-of-line() \n\
  254.      Ctrl<Key>f:    forward-character() \n\
  255.  
  256.  
  257. Answer: Most likely, you have a space at the end of one of the lines (the
  258. first in this case).
  259.  
  260.      Ctrl<Key>a:    beginning-of-line() \n\
  261.                                            ^ space here
  262.  
  263. The second backslash in each line is there to protect the real newline
  264. character and so you must not follow it with anything other than the newline
  265. itself. Otherwise it acts as the end of the resource definition and the
  266. remaining lines are not added.
  267.  
  268.  
  269. -----------------------------------------------------------------------------
  270. Subject: 136)  Where can I get the PanHandler code?
  271.  
  272. Answer: It is available by email from Chuck Ocheret:  chuck@IMSI.COM.
  273.  
  274. -----------------------------------------------------------------------------
  275. Subject: 137) What are these passive grab warnings?  When I destroy certain
  276. widgets I get a stream of messages
  277.  
  278.     Warning: Attempt to remove non-existant passive grab
  279.  
  280.  
  281. Answer: They are meaningless, and you want to ignore them.  Do this (from Kee
  282. Hinckley) by installing an XtWarning handler that explicitly looks for them
  283. and discards them:
  284.  
  285.         static void xtWarnCB(String message) {
  286.            if (asi_strstr(message, "non-existant passive grab", TRUE)) return;
  287.            ...
  288.  
  289. They come from Xt, and (W. Scott Meeks): "it's something that the designers of
  290. Xt decided the toolkit should do. Unfortunately, Motif winds up putting
  291. passive grabs all over the place for the menu system.  On the one hand, we
  292. want to remove all these grabs when menus get destroyed so that they don't
  293. leak memory; on the other hand, it's almost impossible to keep track of all
  294. the grabs, so we have a conservative strategy of ungrabbing any place where a
  295. grab could have been made and we don't explicitly know that there is no grab.
  296. The unfortunate side effect is the little passive grab warning messages.
  297. We're trying to clean these up where possible, but there are some new places
  298. where the warning is generated.  Until we get this completely cleaned up (1.2
  299. maybe), your best bet is probably to use a warning handler."
  300.  
  301. -----------------------------------------------------------------------------
  302. Subject: 138) How do I have more buttons than three in a box?  I want to have
  303. something like a MessageBox (or other widget) with more than three buttons,
  304. but with the same nice appearance.
  305.  
  306. Answer: A SelectionBox is created with four buttons, but the fourth (the Apply
  307. button) is unmanaged. To manage it get its widget ID via
  308. XmSelectionBoxGetChild(parent, XmDIALOG_APPLY_BUTTON) and then XtManage it.
  309. Unmanage all of the other bits in the SelectionBox that you don't want.  If
  310. you want more than four buttons, try two SelectionBoxes (or similar) together
  311. in a container, where all of the unwanted parts of the widgets are unmanaged.
  312.  
  313. Alternatively, build your own dialog:
  314.  
  315. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  316.  * This program is freely distributable without licensing fees and
  317.  * is provided without guarantee or warranty expressed or implied.
  318.  * This program is -not- in the public domain.  This program is
  319.  * taken from the Motif Programming Manual, O'Reilly Volume 6.
  320.  */
  321.  
  322. /* action_area.c -- demonstrate how CreateActionArea() can be used
  323.  * in a real application.  Create what would otherwise be identified
  324.  * as a PromptDialog, only this is of our own creation.  As such,
  325.  * we provide a TextField widget for input.  When the user presses
  326.  * Return, the Ok button is activated.
  327.  */
  328. #include <Xm/DialogS.h>
  329. #include <Xm/PushBG.h>
  330. #include <Xm/PushB.h>
  331. #include <Xm/LabelG.h>
  332. #include <Xm/PanedW.h>
  333. #include <Xm/Form.h>
  334. #include <Xm/RowColumn.h>
  335. #include <Xm/TextF.h>
  336.  
  337. typedef struct {
  338.     char *label;
  339.     void (*callback)();
  340.     caddr_t data;
  341. } ActionAreaItem;
  342.  
  343. static void
  344.     do_dialog(), close_dialog(), activate_cb(),
  345.     ok_pushed(), cancel_pushed(), help();
  346.  
  347. main(argc, argv)
  348. int argc;
  349. char *argv[];
  350. {
  351.     Widget toplevel, button;
  352.     XtAppContext app;
  353.  
  354.     toplevel = XtVaAppInitialize(&app, "Demos",
  355.         NULL, 0, &argc, argv, NULL, NULL);
  356.  
  357.     button = XtVaCreateManagedWidget("Push Me",
  358.         xmPushButtonWidgetClass, toplevel, NULL);
  359.     XtAddCallback(button, XmNactivateCallback, do_dialog, NULL);
  360.  
  361.     XtRealizeWidget(toplevel);
  362.     XtAppMainLoop(app);
  363. }
  364.  
  365. /* callback routine for "Push Me" button.  Actually, this represents
  366.  * a function that could be invoked by any arbitrary callback.  Here,
  367.  * we demonstrate how one can build a standard customized dialog box.
  368.  * The control area is created here and the action area is created in
  369.  * a separate, generic routine: CreateActionArea().
  370.  */
  371. static void
  372. do_dialog(w, file)
  373. Widget w; /* will act as dialog's parent */
  374. char *file;
  375. {
  376.     Widget dialog, pane, rc, label, text_w, action_a;
  377.     XmString string;
  378.     extern Widget CreateActionArea();
  379.     Arg args[10];
  380.     static ActionAreaItem action_items[] = {
  381.         { "Ok",     ok_pushed,     NULL          },
  382.         { "Cancel", cancel_pushed, NULL          },
  383.         { "Close",  close_dialog,  NULL          },
  384.         { "Help",   help,          "Help Button" },
  385.     };
  386.  
  387.     /* The DialogShell is the Shell for this dialog.  Set it up so
  388.      * that the "Close" button in the window manager's system menu
  389.      * destroys the shell (it only unmaps it by default).
  390.      */
  391.     dialog = XtVaCreatePopupShell("dialog",
  392.         xmDialogShellWidgetClass, XtParent(w),
  393.         XmNtitle,  "Dialog Shell",     /* give arbitrary title in wm */
  394.         XmNdeleteResponse, XmDESTROY,  /* system menu "Close" action */
  395.         NULL);
  396.  
  397.     /* now that the dialog is created, set the Close button's
  398.      * client data, so close_dialog() will know what to destroy.
  399.      */
  400.     action_items[2].data = (caddr_t)dialog;
  401.  
  402.     /* Create the paned window as a child of the dialog.  This will
  403.      * contain the control area (a Form widget) and the action area
  404.      * (created by CreateActionArea() using the action_items above).
  405.      */
  406.     pane = XtVaCreateWidget("pane", xmPanedWindowWidgetClass, dialog,
  407.         XmNsashWidth,  1,
  408.         XmNsashHeight, 1,
  409.         NULL);
  410.  
  411.     /* create the control area (Form) which contains a
  412.      * Label gadget and a List widget.
  413.      */
  414.     rc = XtVaCreateWidget("control_area", xmRowColumnWidgetClass, pane, NULL);
  415.     string = XmStringCreateSimple("Type Something:");
  416.     XtVaCreateManagedWidget("label", xmLabelGadgetClass, rc,
  417.         XmNlabelString,    string,
  418.         XmNleftAttachment, XmATTACH_FORM,
  419.         XmNtopAttachment,  XmATTACH_FORM,
  420.         NULL);
  421.     XmStringFree(string);
  422.  
  423.     text_w = XtVaCreateManagedWidget("text-field",
  424.         xmTextFieldWidgetClass, rc, NULL);
  425.  
  426.     /* RowColumn is full -- now manage */
  427.     XtManageChild(rc);
  428.  
  429.     /* Set the client data "Ok" and "Cancel" button's callbacks. */
  430.     action_items[0].data = (caddr_t)text_w;
  431.     action_items[1].data = (caddr_t)text_w;
  432.  
  433.     /* Create the action area -- we don't need the widget it returns. */
  434.     action_a = CreateActionArea(pane, action_items, XtNumber(action_items));
  435.  
  436.     /* callback for Return in TextField.  Use action_a as client data */
  437.     XtAddCallback(text_w, XmNactivateCallback, activate_cb, action_a);
  438.  
  439.     XtManageChild(pane);
  440.     XtPopup(dialog, XtGrabNone);
  441. }
  442.  
  443. /*--------------*/
  444. /* The next four functions are the callback routines for the buttons
  445.  * in the action area for the dialog created above.  Again, they are
  446.  * simple examples, yet they demonstrate the fundamental design approach.
  447.  */
  448. static void
  449. close_dialog(w, shell)
  450. Widget w, shell;
  451. {
  452.     XtDestroyWidget(shell);
  453. }
  454.  
  455. /* The "ok" button was pushed or the user pressed Return */
  456. static void
  457. ok_pushed(w, text_w, cbs)
  458. Widget w, text_w;         /* the text widget is the client data */
  459. XmAnyCallbackStruct *cbs;
  460. {
  461.     char *text = XmTextFieldGetString(text_w);
  462.  
  463.     printf("String = %s0, text);
  464.     XtFree(text);
  465. }
  466.  
  467. static void
  468. cancel_pushed(w, text_w, cbs)
  469. Widget w, text_w;         /* the text field is the client data */
  470. XmAnyCallbackStruct *cbs;
  471. {
  472.     /* cancel the whole operation; reset to NULL. */
  473.     XmTextFieldSetString(text_w, "");
  474. }
  475.  
  476. static void
  477. help(w, string)
  478. Widget w;
  479. String string;
  480. {
  481.     puts(string);
  482. }
  483. /*--------------*/
  484.  
  485. /* When Return is pressed in TextField widget, respond by getting
  486.  * the designated "default button" in the action area and activate
  487.  * it as if the user had selected it.
  488.  */
  489. static void
  490. activate_cb(text_w, client_data, cbs)
  491. Widget text_w;              /* user pressed Return in this widget */
  492. XtPointer client_data;        /* action_area passed as client data */
  493. XmAnyCallbackStruct *cbs;   /* borrow the "event" field from this */
  494. {
  495.     Widget dflt, action_area = (Widget)client_data;
  496.  
  497.     XtVaGetValues(action_area, XmNdefaultButton, &dflt, NULL);
  498.     if (dflt) /* sanity check -- this better work */
  499.         /* make the default button think it got pushed.  This causes
  500.          * "ok_pushed" to be called, but XtCallActionProc() causes
  501.          * the button appear to be activated as if the user selected it.
  502.          */
  503.         XtCallActionProc(dflt, "ArmAndActivate", cbs->event, NULL, 0);
  504. }
  505.  
  506. #define TIGHTNESS 20
  507.  
  508. Widget
  509. CreateActionArea(parent, actions, num_actions)
  510. Widget parent;
  511. ActionAreaItem *actions;
  512. int num_actions;
  513. {
  514.     Widget action_area, widget;
  515.     int i;
  516.  
  517.     action_area = XtVaCreateWidget("action_area", xmFormWidgetClass, parent,
  518.         XmNfractionBase, TIGHTNESS*num_actions - 1,
  519.         XmNleftOffset,   10,
  520.         XmNrightOffset,  10,
  521.         NULL);
  522.  
  523.     for (i = 0; i < num_actions; i++) {
  524.         widget = XtVaCreateManagedWidget(actions[i].label,
  525.             xmPushButtonWidgetClass, action_area,
  526.             XmNleftAttachment,       i? XmATTACH_POSITION : XmATTACH_FORM,
  527.             XmNleftPosition,         TIGHTNESS*i,
  528.             XmNtopAttachment,        XmATTACH_FORM,
  529.             XmNbottomAttachment,     XmATTACH_FORM,
  530.             XmNrightAttachment,
  531.                     i != num_actions-1? XmATTACH_POSITION : XmATTACH_FORM,
  532.             XmNrightPosition,        TIGHTNESS*i + (TIGHTNESS-1),
  533.             XmNshowAsDefault,        i == 0,
  534.             XmNdefaultButtonShadowThickness, 1,
  535.             NULL);
  536.         if (actions[i].callback)
  537.             XtAddCallback(widget, XmNactivateCallback,
  538.                 actions[i].callback, actions[i].data);
  539.         if (i == 0) {
  540.             /* Set the action_area's default button to the first widget
  541.              * created (or, make the index a parameter to the function
  542.              * or have it be part of the data structure). Also, set the
  543.              * pane window constraint for max and min heights so this
  544.              * particular pane in the PanedWindow is not resizable.
  545.              */
  546.             Dimension height, h;
  547.             XtVaGetValues(action_area, XmNmarginHeight, &h, NULL);
  548.             XtVaGetValues(widget, XmNheight, &height, NULL);
  549.             height += 2 * h;
  550.             XtVaSetValues(action_area,
  551.                 XmNdefaultButton, widget,
  552.                 XmNpaneMaximum,   height,
  553.                 XmNpaneMinimum,   height,
  554.                 NULL);
  555.         }
  556.     }
  557.  
  558.     XtManageChild(action_area);
  559.  
  560.     return action_area;
  561. }
  562.  
  563.  
  564.  
  565. -----------------------------------------------------------------------------
  566. Subject: 139)  How do I create a "busy working cursor"?
  567.  
  568. Answer: - in Baudouin's code (following), the idea is to keep in an array an
  569. up-to-date list of all shells used in the application, and set for all of them
  570. the cursor to a watch or to the default cursor, with the 2 functions provided.
  571.  
  572. - in Dan Heller's code (later), the idea is to turn on the watch cursor for
  573. the top-level shell only, popup a working window to possibly abort the
  574. callback, and manage some expose events during the callback.
  575.  
  576. - in the FAQ for comp.windows.x (#113), the idea is to bring a large window on
  577. top of the application, hide all windows below it, and turn on the watch
  578. cursor on this large window. Unmapping the large window resets the default
  579. cursor, mapping it turns on the watch cursor.
  580.  
  581. From Baudouin Raoult (mab@ecmwf.co.uk)
  582.  
  583. void my_SetWatchCursor(w)
  584. Widget w;
  585. {
  586.         static Cursor watch = NULL;
  587.  
  588.         if(!watch)
  589.                 watch = XCreateFontCursor(XtDisplay(w),XC_watch);
  590.  
  591.         XDefineCursor(XtDisplay(w),XtWindow(w),watch);
  592.         XmUpdateDisplay(w);
  593. }
  594.  
  595. void my_ResetCursor(w)
  596. Widget w;
  597. {
  598.         XUndefineCursor(XtDisplay(w),XtWindow(w));
  599.         XmUpdateDisplay(w);
  600. }
  601.  
  602.  
  603. Answer: A solution with lots of bells and whistles is
  604.  
  605. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  606.  * This program is freely distributable without licensing fees and
  607.  * is provided without guarantee or warrantee expressed or implied.
  608.  * This program is -not- in the public domain.
  609.  */
  610.  
  611. /* busy.c -- demonstrate how to use a WorkingDialog and to process
  612.  * only "important" events.  e.g., those that may interrupt the
  613.  * task or to repaint widgets for exposure.  Set up a simple shell
  614.  * and a widget that, when pressed, immediately goes into its own
  615.  * loop.  First, "lock" the shell so that a timeout cursor is set on
  616.  * the shell and pop up a WorkingDialog.  Then enter loop ... sleep
  617.  * for one second ten times, checking between each interval to see
  618.  * if the user clicked the Stop button or if any widgets need to be
  619.  * refreshed.  Ignore all other events.
  620.  *
  621.  * main() and get_busy() are stubs that would be replaced by a real
  622.  * application; all other functions can be used "as is."
  623.  */
  624. #include <Xm/MessageB.h>
  625. #include <Xm/PushB.h>
  626. #include <X11/cursorfont.h>
  627.  
  628. Widget shell;
  629. void TimeoutCursors();
  630. Boolean CheckForInterrupt();
  631.  
  632. main(argc, argv)
  633. int argc;
  634. char *argv[];
  635. {
  636.     XtAppContext app;
  637.     Widget button;
  638.     XmString label;
  639.     void get_busy();
  640.  
  641.     shell = XtVaAppInitialize(&app, "Demos",
  642.         NULL, 0, &argc, argv, NULL, NULL);
  643.  
  644.     label = XmStringCreateSimple(
  645.         "Boy, is *this* going to take a long time.");
  646.     button = XtVaCreateManagedWidget("button",
  647.         xmPushButtonWidgetClass, shell,
  648.         XmNlabelString,          label,
  649.         NULL);
  650.     XmStringFree(label);
  651.     XtAddCallback(button, XmNactivateCallback, get_busy, argv[1]);
  652.  
  653.     XtRealizeWidget(shell);
  654.     XtAppMainLoop(app);
  655. }
  656.  
  657. void
  658. get_busy(widget)
  659. Widget widget;
  660. {
  661.     int n;
  662.  
  663.     TimeoutCursors(True, True);
  664.     for (n = 0; n < 10; n++) {
  665.         sleep(1);
  666.         if (CheckForInterrupt()) {
  667.             puts("Interrupt!");
  668.             break;
  669.         }
  670.     }
  671.     if (n == 10)
  672.         puts("done.");
  673.     TimeoutCursors(False, NULL);
  674. }
  675.  
  676. /* The interesting part of the program -- extract and use at will */
  677. static Boolean stopped;  /* True when user wants to stop processing */
  678. static Widget dialog;    /* WorkingDialog displayed when timed out */
  679.  
  680. /* timeout_cursors() turns on the "watch" cursor over the application
  681.  * to provide feedback for the user that he's going to be waiting
  682.  * a while before he can interact with the appliation again.
  683.  */
  684. void
  685. TimeoutCursors(on, interruptable)
  686. int on, interruptable;
  687. {
  688.     static int locked;
  689.     static Cursor cursor;
  690.     extern Widget shell;
  691.     XSetWindowAttributes attrs;
  692.     Display *dpy = XtDisplay(shell);
  693.     XEvent event;
  694.     Arg args[1];
  695.     XmString str;
  696.     extern void stop();
  697.  
  698.     /* "locked" keeps track if we've already called the function.
  699.      * This allows recursion and is necessary for most situations.
  700.      */
  701.     on? locked++ : locked--;
  702.     if (locked > 1 || locked == 1 && on == 0)
  703.         return; /* already locked and we're not unlocking */
  704.  
  705.     stopped = False; /* doesn't matter at this point; initialize */
  706.     if (!cursor) /* make sure the timeout cursor is initialized */
  707.         cursor = XCreateFontCursor(dpy, XC_watch);
  708.  
  709.     /* if "on" is true, then turn on watch cursor, otherwise, return
  710.      * the shell's cursor to normal.
  711.      */
  712.     attrs.cursor = on? cursor : None;
  713.  
  714.     /* change the main application shell's cursor to be the timeout
  715.      * cursor (or to reset it to normal).  If other shells exist in
  716.      * this application, they will have to be listed here in order
  717.      * for them to have timeout cursors too.
  718.      */
  719.     XChangeWindowAttributes(dpy, XtWindow(shell), CWCursor, &attrs);
  720.  
  721.     XFlush(dpy);
  722.  
  723.     if (on) {
  724.         /* we're timing out, put up a WorkingDialog.  If the process
  725.          * is interruptable, allow a "Stop" button.  Otherwise, remove
  726.          * all actions so the user can't stop the processing.
  727.          */
  728.         str = XmStringCreateSimple("Busy.  Please Wait.");
  729.         XtSetArg(args[0], XmNmessageString, str);
  730.         dialog = XmCreateWorkingDialog(shell, "Busy", args, 1);
  731.         XmStringFree(str);
  732.         XtUnmanageChild(
  733.             XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON));
  734.         if (interruptable) {
  735.             str = XmStringCreateSimple("Stop");
  736.             XtVaSetValues(dialog, XmNcancelLabelString, str, NULL);
  737.             XmStringFree(str);
  738.             XtAddCallback(dialog, XmNcancelCallback, stop, NULL);
  739.         } else
  740.             XtUnmanageChild(
  741.                 XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
  742.         XtUnmanageChild(
  743.             XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
  744.         XtManageChild(dialog);
  745.     } else {
  746.         /* get rid of all button and keyboard events that occured
  747.          * during the time out.  The user shouldn't have done anything
  748.          * during this time, so flush for button and keypress events.
  749.          * KeyRelease events are not discarded because accelerators
  750.          * require the corresponding release event before normal input
  751.          * can continue.
  752.          */
  753.         while (XCheckMaskEvent(dpy,
  754.                 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
  755.                 | PointerMotionMask | KeyPressMask, &event)) {
  756.             /* do nothing */;
  757.         }
  758.         XtDestroyWidget(dialog);
  759.     }
  760.